Appearance
原生手势控制 1
本节目标:理解“原生手势控制 1”的核心思路,并能把它用于实际开发或面试表达。 思路:
- 先创建自定义的手势事件
let gesturestart = new CustomEvent('gesturestart'); //手势开始
let gesturechange = new CustomEvent('gesturechange'); //手势变化,缩放,旋转等
let gestureend = new CustomEvent('gestureend'); //手势结束
let swipeMove = new CustomEvent('swipemove'); //滑动
let doubleTouch = new CustomEvent('doubletouch'); //双击
let oneTouch = new CustomEvent('onetouch'); //点击
- 再给对象绑定原生事件处理方法,当这些原生事件发生时,处理方法中主要是根据touches属性来区分手势,然后保存一些关键数据到自定义事件中,并触发dispatch相应的手势事件
this.imgRef.addEventListener('touchstart', handleTouchStart, false);
this.imgRef.addEventListener('touchmove', handleTouchMove, false);
this.imgRef.addEventListener('touchend', handleTouchEnd, false);
this.imgRef.addEventListener('touchcancel', handleTouchCancel, false);- 再调用一个方法,让事件对象监听我们的自定义手势事件,这些手势事件会触发一个统一的手势处事件处理方法,主要根据event.type来进行相应的业务逻辑操作
previewImgs = () => {
this.imgRef.addEventListener('gestureStart', gestureFun, false);
this.imgRef.addEventListener('gesturechange', gestureFun, false);
this.imgRef.addEventListener('gestureEnd', gestureFun, false);
this.imgRef.addEventListener('swipemove', gestureFun, false);
this.imgRef.addEventListener('doubletouch', gestureFun, false);
this.imgRef.addEventListener('onetouch', gestureFun, false); function gestureFun(e) {
let currImgIndex = parseInt(e.target.id) || 0;
const { startX, startY, imgNum, left: rawLeft } = this.state;
let left = 0;
switch (e.type) {
case "gesturestart":
break;
case "gesturechange":
break;
case "swipemove":
if (e.direction === 'left') {
//最后一张左拉的情况
if (Math.abs(rawLeft) >= 100 * (imgNum - 1)) {
left = rawLeft;
return;
}
left = rawLeft - 100;
currImgIndex++;
}
if (e.direction === 'right') {
//第一张右拉的情况
if (rawLeft === 0) {
left = 0;
return;
}
left = rawLeft + 100;
currImgIndex--;
}
this.setState({ left, currImgIndex });
break;
default:
break;
}
}}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<style>
body {
position: absolute;
width: 100%;
height: 100%;
margin: 0;
text-align: center;
}
.img1 {
width: 60%;
margin: auto;
}
.bgM {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
background-color: rgba(0, 0, 0, 0.85);
overflow: hidden;
}
.bgM img {
width: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1001;
margin: auto;
}
</style>
</head>
<body>
<h4>点击图片预览
</h4>
<img
class="img1 preview"
src="http://lc-yee5xnhu.cn-n1.lcfile.com/56ac839df83d3bcdc63b.jpg"
alt=""
/>
<script>
window.onload = function() {
//点击图片进入预览
var $Dom = document.querySelector(".preview");
$Dom.onclick = function() {
var temp = this.src;
var objE = document.createElement("div");
objE.innerHTML =
'<div class="bgM" >' +
'<img src="' +
temp +
'" id="img_scan" class="img-custom-img2"/>' +
"</div>";
document.body.appendChild(objE.children[0]);
//退出图片预览事件
var $bg = document.querySelector(".bgM");
$bg.onclick = function(event) {
event.stopPropagation();
var dm = document.querySelector(".bgM");
document.body.removeChild(dm);
};
// var $img = document.querySelector(".img-custom-img2");
// $img.onclick = function(event) {
// debugger
// event.stopPropagation();
// };
createEvent(); //自定义事件
previewImg(); //图片预览事件监听
};
};
/*
*自定义移动端手势事件* 事件:* - gesturestart 手势事件开始* - gesturechange 手势缩放* - gestureend 手势事件结束* - swipeMove 单指滑动* - doubleTouch 双击* - oneTouch 单击
*/
var createEvent = function() {
var $bm = document.querySelector(".bgM");
var isTouch = false;
var isDoubleTouch = false; //是否为多触点
var start = []; //存放触点坐标
var now, delta; //当前时间,两次触发事件时间差
var timer = null;
var startPosition, movePosition, endPosition; //滑动起点,移动,结束点坐标//事件声明
var gesturestart = new CustomEvent("gesturestart");
var gesturechange = new CustomEvent("gesturechange");
var gestureend = new CustomEvent("gestureend");
var swipeMove = new CustomEvent("swipeMove");
var doubleTouch = new CustomEvent("doubleTouch");
var oneTouch = new CustomEvent("oneTouch");
//监听touchstart事件
$bm.addEventListener(
"touchstart",
function(e) {
//e.preventDefault();
if (e.touches.length >= 2) {
//判断是否有两个点在屏幕上
isDoubleTouch = true;
start = e.touches; //得到第一组两个点
var screenMinPoint = getMidpoint(start[0], start[1]); //获取两个触点中心坐标
gesturestart.midPoint = [
screenMinPoint[0] - e.target.offsetLeft,
screenMinPoint[1] - e.target.offsetTop
]; //获取中心点坐标相对目标元素坐标
e.target.dispatchEvent(gesturestart);
} else {
delta = Date.now() - now; //计算两次点击时间差
now = Date.now();
startPosition = [e.touches[0].pageX, e.touches[0].pageY];
if (delta > 0 && delta <= 250) {
//双击事件
clearTimeout(timer);
doubleTouch.position = [
e.touches[0].pageX - e.target.offsetLeft,
e.touches[0].pageY - e.target.offsetTop
];
e.target.dispatchEvent(doubleTouch);
} else {
//滑动事件
timer = setTimeout(function() {
e.target.dispatchEvent(oneTouch); //单击事件
}, 450);
}
isTouch = true;
}
},
false
);
//监听touchmove事件
$bm.addEventListener(
"touchmove",
function(e) {
//e.preventDefault();
clearTimeout(timer);
if (e.touches.length >= 2 && isDoubleTouch) {
//手势事件
var now = e.touches; //得到第二组两个点
var scale =
getDistance(now[0], now[1]) / getDistance(start[0], start[1]); //得到缩放比例
var rotation =
getAngle(now[0], now[1]) - getAngle(start[0], start[1]); //得到旋转角度差
gesturechange.scale = scale.toFixed(2);
gesturechange.rotation = rotation.toFixed(2);
e.target.dispatchEvent(gesturechange);
} else if (isTouch) {
movePosition = [e.touches[0].pageX, e.touches[0].pageY];
console.log(
"touches:",
e.touches,
"start:",
startPosition,
"movePostion:",
movePosition
);
endPosition = movePosition;
movePosition = [
movePosition[0] - startPosition[0],
movePosition[1] - startPosition[1]
];
startPosition = [e.touches[0].pageX, e.touches[0].pageY];
swipeMove.distance = [
movePosition[0].toFixed(2),
movePosition[1].toFixed(2)
];
e.target.dispatchEvent(swipeMove);
}
},
false
);
//监听touchend事件
$bm.addEventListener(
"touchend",
function(e) {
if (isDoubleTouch) {
isDoubleTouch = false;
gestureend.position = endPosition;
e.target.dispatchEvent(gestureend);
}
},
false
);
/*
*两点的距离
*/
function getDistance(p1, p2) {
var x = p2.pageX - p1.pageX,
y = p2.pageY - p1.pageY;
return Math.sqrt(x * x + y * y);
}
/*
*两点的夹角
*/
function getAngle(p1, p2) {
var x = p1.pageX - p2.pageX,
y = p1.pageY - p2.pageY;
return (Math.atan2(y, x) * 180) / Math.PI;
}
/*
*获取中点
*/
function getMidpoint(p1, p2) {
var x = (p1.pageX + p2.pageX) / 2,
y = (p1.pageY + p2.pageY) / 2;
return [x, y];
}
};
/*
*事件处理
*/
var previewImg = function() {
var $imgs = document.querySelector("#img_scan");
var clientWidth = document.body.clientWidth; //窗口宽
var clientHeight = document.body.clientHeight; //窗口高
var imgWidth = parseInt(window.getComputedStyle($imgs).width); //图片宽
var imgHeight = parseInt(window.getComputedStyle($imgs).height); //图片高
$imgs.addEventListener("gesturestart", gesturef, false);
$imgs.addEventListener("gesturechange", gesturef, false);
$imgs.addEventListener("gestureend", gesturef, false);
$imgs.addEventListener("swipeMove", gesturef, false);
$imgs.addEventListener("doubleTouch", gesturef, false);
$imgs.addEventListener("oneTouch", gesturef, false);
var tMatrix = [1, 0, 0, 1, 0, 0]; //x缩放,无,无,y缩放,x平移,y平移
var originLast,
maxSwipeLeft,
maxSwipeRight,
maxSwipeTop,
maxSwipeBottom; //上下左右可拖动距离
function maxMove() {
//最大可拖动范围
var sca = tMatrix[0];
maxSwipeLeft = Math.abs(sca - 1) * originLast[0];
maxSwipeRight = Math.abs(sca - 1) * (imgWidth - originLast[0]);
maxSwipeTop = Math.abs(sca - 1) * originLast[1];
maxSwipeBottom = Math.abs(sca - 1) * (imgHeight - originLast[1]);
}
function gesturef(event) {
switch (event.type) {
case "gesturestart":
var x = event.midPoint[0];
var y = event.midPoint[1];
originLast = event.midPoint;
$imgs.style.transformOrigin = x + "px " + y + "px";
break;
case "gesturechange":
var sc = parseFloat(event.scale);
tMatrix[0] =
tMatrix[0] + sc - 1 > 0.5 && tMatrix[0] + sc - 1 < 3
? tMatrix[0] + sc - 1
: tMatrix[0];
tMatrix[3] =
tMatrix[3] + sc - 1 > 0.5 && tMatrix[3] + sc - 1 < 3
? tMatrix[3] + sc - 1
: tMatrix[3];
var temp = tMatrix.join(",");
$imgs.style.transform = "matrix(" + temp + ")";
break;
case "gestureend":
maxMove();
break;
case "swipeMove":
if (
!maxSwipeLeft ||
!maxSwipeRight ||
!maxSwipeTop ||
!maxSwipeBottom
)
return;
if (event.distance[0] > 0 && maxSwipeLeft < tMatrix[4]) return;
if (event.distance[0] < 0 && maxSwipeRight < -tMatrix[4]) return;
if (event.distance[1] > 0 && maxSwipeTop < tMatrix[5]) return;
if (event.distance[1] < 0 && maxSwipeBottom < -tMatrix[5]) return;
tMatrix[4] = tMatrix[4] + parseInt(event.distance[0]);
tMatrix[5] = tMatrix[5] + parseInt(event.distance[1]);
var temp = tMatrix.join(",");
$imgs.style.transform = "matrix(" + temp + ")";
break;
case "doubleTouch":
originLast = event.position;
$imgs.style.transformOrigin =
event.position[0] + "px " + event.position[1] + "px";
tMatrix[0] = 2; //缩放倍数为
2
tMatrix[3] = 2;
var temp = tMatrix.join(",");
$imgs.style.transform = "matrix(" + temp + ")";
maxMove();
break;
case "oneTouch":
var $bg = document.querySelector(".bgM");
document.body.removeChild($bg);
break;
}
}
};
</script>
</body>
</html>